package flextv.search.logic {

import flash.events.EventDispatcher;
import flash.events.IEventDispatcher;

import flextv.core.logic.Logger;
import flextv.core.logic.Util;
import flextv.search.vo.SearchItem;

import mx.collections.ArrayCollection;
import mx.logging.ILogger;
import mx.rpc.IResponder;
import mx.rpc.events.ResultEvent;
import mx.rpc.http.HTTPService;
	

public class SearchServiceImpl extends EventDispatcher implements ISearchService {
	
	private static const LOG: ILogger = Logger.getLog(SearchServiceImpl);
	
	private static const YOUTUBE_SEARCH_URL: String = "http://gdata.youtube.com/feeds/api/videos";
	
	private static const MAX_RESULT_COUNT:uint = 30; // TODO pager view start-index http param; max possible is 50 anyway...
	
	
	
	public function SearchServiceImpl(target: IEventDispatcher=null) {
		super(target);
	}
	
	public function search(term: String, responder: IResponder): void {
		LOG.info("search(term="+term+")");
		
		const param: QueryParam = new QueryParam();
		param.queryString = escape(term);
		const queryUrl: String = constructRequestUrl(param);
		
		const httpService: HTTPService = new HTTPService();
		httpService.url = queryUrl; 
		
		// httpService.addEventListener(FaultEvent.FAULT, this._fnFault);
		httpService.addEventListener(ResultEvent.RESULT, function(event: ResultEvent): void {
			LOG.debug("onResult(event="+event+")");
			var entries: ArrayCollection = event.result.feed.entry as ArrayCollection;
			var result: ArrayCollection = new ArrayCollection();
			
			var resultCount:uint = event.result.feed.totalResults;
			LOG.debug("resultCount = " + resultCount); // TODO pager: if resultCount > page.display_size => show pager
			
			if(resultCount > 0) {
				for (var i: int = 0; i < entries.length; i++) {
					
					var entry:Object = entries.getItemAt(i);
					
					const entrySwfUrl: String = extractSwfUrl(entry);
					
					const watchIdStart: int = entrySwfUrl.indexOf("/v/");
					const watchIdEnd: int = entrySwfUrl.indexOf("&");
					const watchId: String = entrySwfUrl.substr(watchIdStart + 3, watchIdEnd - watchIdStart - 3); 
					// LOG.finest("extracted swf source: [" + entrySwfSource + "]");
					const yid: String = extractYidFromUrl(entrySwfUrl);
					if(yid != watchId) {
						throw new Error("yid != watchId => yid:["+yid+"], watchId:["+watchId+"]");
					}
					
					const entryTitle: String = entry.title;
					const duration: uint = entry.group.duration.seconds as uint;
					const thumbnailUrl: String = Util.extractFirstThumbnail(entry);
					result.addItem(new SearchItem(yid, entryTitle, duration, thumbnailUrl));
				}
			}
			
			responder.result(result);
		});
		
		LOG.debug("httpService.send(queryUrl="+queryUrl+")");
		httpService.send();
		
	}
	
	
		
	
	private static function constructRequestUrl(param: QueryParam):String {
		var url:String =  YOUTUBE_SEARCH_URL + "?";
		
		var first:Boolean = true;
		param.forEach(function (key: String, value: Object): void {
			if(first == true) first = false;
			else url += "&";
			url += key + "=" + value;
		});
		
		return url;
	}
	
	/**
	 * @return eg: "http://www.youtube.com/v/LNNJXJ3JkK0&f=gdata_videos"
	 */
	private static function extractSwfUrl(item: Object): String {
		if(item.group.content is ArrayCollection) {
			for(var i: int = 0; i < item.group.content.length; i++) {
				var obj: Object = item.group.content[i];
				if(obj.type == "application/x-shockwave-flash") {
					return obj.url;
				}
			}
			
		} else if(item.group.content is Object) { // ObjectProxy
			var c: Object = Object(item.group.content);
			if(c.type == "application/x-shockwave-flash") {
				return c.url;
			}
			
		}
		
		// FIXME can have no "group.content" at all!!! TODO: inspect user player tag instead
		throw new Error("Could not extract swf source from item: " + item);
		
	}
	
	private static function extractYidFromUrl(url: String): String {
		var posLastSlash: int = url.lastIndexOf("/");
		var posFirstAmp: int = url.indexOf("&");
		var lenId: int = posFirstAmp - (posLastSlash + 1);
		return url.substr(posLastSlash + 1, lenId);
	}

	
}
}